package com.kensure.shike.weixinpay.service;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.stereotype.Service;

import com.kensure.shike.constant.BusiConstant;
import com.kensure.shike.weixinpay.model.WXPayinfo;
import com.kensure.shike.weixinpay.model.WXPayinfo2;
import com.kensure.shike.weixinpay.model.WXPrePay;
import com.kensure.shike.weixinpay.model.WXTixianChaXuninfo;
import com.kensure.shike.weixinpay.model.WXTixianinfo;
import com.kensure.shike.weixinpay.utils.PayUtil;
import com.kensure.shike.weixinpay.utils.UUIDHexGenerator;
import com.kensure.shike.weixinpay.utils.XmlUtil;

@Service
public class WeiXinPaymentService {

	/**
	 *
	 * @param openId
	 * @param total_fee
	 *            订单总金额，单位为分。
	 * @param body
	 *            商品简单描述，该字段请按照规范传递。 例：腾讯充值中心-心悦会员充值
	 * @param attach
	 *            附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用。 例：广州分店
	 * @return
	 * @throws UnsupportedEncodingException
	 * @throws DocumentException
	 */

	public WXPrePay payment(WXPayinfo info) {
		WXPayinfo2 paymentPo = new WXPayinfo2(info);

		// 把请求参数打包成数组
		// 除去数组中的空值和签名参数
		Map sPara = PayUtil.paraFilter(paymentPo.toUnitMap());
		String prestr = PayUtil.createLinkString(sPara); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

		// MD5运算生成签名
		String mysign = PayUtil.sign(prestr).toUpperCase();
		paymentPo.setSign(mysign);
		// 打包要发送的xml
		String respXml = XmlUtil.messageToXML(paymentPo);
		// 打印respXml发现，得到的xml中有“__”不对，应该替换成“_”
		respXml = respXml.replace("__", "_");
		String param = respXml;

		String result = PayUtil.httpRequest(BusiConstant.wxpay_url, "POST", param);
		System.out.println("请求微信预支付接口，返回 result：" + result);
		// 将解析结果存储在Map中
		Map<String, String> map = xmlToMap(result);
		// 返回信息
		String return_code = map.get("return_code");// 返回状态码
		String return_msg = map.get("return_msg");// 返回信息
		String result_code = map.get("result_code");// 返回状态码

		System.out.println("请求微信预支付接口，返回 code：" + return_code);
		System.out.println("请求微信预支付接口，返回 msg：" + return_msg);

		WXPrePay prepay = new WXPrePay();
		if ("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)) {
			// 业务结果
			String prepay_id = map.get("prepay_id");// 返回的预付单信息
			String nonceStr = UUIDHexGenerator.generate();
			prepay.setNonceStr(nonceStr);
			prepay.setPrepayId(prepay_id);
			Long timeStamp = System.currentTimeMillis() / 1000;
			prepay.setTimeStamp(timeStamp + "");
			String stringSignTemp = "appId=" + paymentPo.getAppid() + "&nonceStr=" + nonceStr + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
			// 再次签名
			String paySign = PayUtil.sign(stringSignTemp).toUpperCase();
			prepay.setSign(paySign);
		}
		return prepay;
	}

	/**
	 * 提现功能接口实现
	 */
	public Map<String, String> tixian(WXPayinfo info) {
		WXTixianinfo paymentPo = new WXTixianinfo(info);

		// 把请求参数打包成数组
		// 除去数组中的空值和签名参数
		Map sPara = PayUtil.paraFilter(paymentPo.toUnitMap());
		String prestr = PayUtil.createLinkString(sPara); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

		// MD5运算生成签名
		String mysign = PayUtil.sign(prestr).toUpperCase();
		paymentPo.setSign(mysign);
		// 打包要发送的xml
		String respXml = XmlUtil.messageToXML(paymentPo);
		// 打印respXml发现，得到的xml中有“__”不对，应该替换成“_”
		respXml = respXml.replace("__", "_");
		String param = respXml;

		String result = PayUtil.httpSslRequest(BusiConstant.wxtixian_url, param);
		System.out.println("请求微企业支付接口，返回 result：" + result);
		// 将解析结果存储在Map中
		Map<String, String> map = xmlToMap(result);
		return map;
	}

	
	
	
	/**
	 * 提现查询接口
	 */
	public Map<String, String> tixianChaXun(WXPayinfo info) {
		WXTixianChaXuninfo paymentPo = new WXTixianChaXuninfo(info);

		// 把请求参数打包成数组
		// 除去数组中的空值和签名参数
		Map sPara = PayUtil.paraFilter(paymentPo.toUnitMap());
		String prestr = PayUtil.createLinkString(sPara); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串

		// MD5运算生成签名
		String mysign = PayUtil.sign(prestr).toUpperCase();
		paymentPo.setSign(mysign);
		// 打包要发送的xml
		String respXml = XmlUtil.messageToXML(paymentPo);
		// 打印respXml发现，得到的xml中有“__”不对，应该替换成“_”
		respXml = respXml.replace("__", "_");
		String param = respXml;

		String result = PayUtil.httpSslRequest(BusiConstant.wxtixianchaxun_url, param);
		System.out.println("请求微企业支付查询接口，返回 result：" + result);
		// 将解析结果存储在Map中
		Map<String, String> map = xmlToMap(result);
		return map;
	}
	/**
	 * 将string解析成xml，并将其中的参数放到map中返回
	 * 
	 * @param result
	 * @return
	 */
	private Map<String, String> xmlToMap(String result) {
		// 将解析结果存储在Map中
		Map<String, String> map = new HashMap<String, String>();
		InputStream in = null;
		try {
			in = new ByteArrayInputStream(result.getBytes("UTF-8"));
			// 读取输入流
			SAXReader reader = new SAXReader();
			Document document = reader.read(in);
			// 得到xml根元素
			Element root = document.getRootElement();
			// 得到根元素的所有子节点
			List<Element> elementList = root.elements();
			for (Element element : elementList) {
				map.put(element.getName(), element.getText());
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return map;
	}

}